package com.ypan.uninstaller.all;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.preference.PreferenceManager;
import android.support.v4.app.DialogFragment;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.ListView;
import android.widget.TextView;

import com.ypan.uninstaller.BaseFragment;
import com.ypan.uninstaller.MainApp;
import com.ypan.uninstaller.Preference;
import com.ypan.uninstaller.R;
import com.ypan.uninstaller.adapter.ApkInfo;
import com.ypan.uninstaller.adapter.AppListAdapter;
import com.ypan.uninstaller.logger.SLog;
import com.ypan.uninstaller.utils.Define;
import com.ypan.uninstaller.utils.DialogHelper;
import com.ypan.uninstaller.utils.DialogHelper.BackupDlgFragment;
import com.ypan.uninstaller.utils.DialogHelper.BackupListener;
import com.ypan.uninstaller.utils.DialogHelper.OptionDlgFragment;
import com.ypan.uninstaller.utils.DialogHelper.OptionListener;
import com.ypan.uninstaller.utils.DialogHelper.SortListener;
import com.ypan.uninstaller.utils.FileUtils;
import com.ypan.uninstaller.utils.PackageUtils;
import com.ypan.uninstaller.utils.SharePreferences;

/**
 * @ClassName: UninstallFragment
 * @Description: UninstallFragment
 * @author Administrator
 * @date 2012-8-15 下午10:53:40
 */
public class UninstallFragment extends BaseFragment implements
		OnItemClickListener, OnItemLongClickListener {

	//
	private static final String TAG = UninstallFragment.class.getSimpleName();
	//
	private ArrayList<ApkInfo> mApkInfoList = null;
	private AppListAdapter mAdapter = null;
	//
	private String mCurFilter;
	private ListView mListView = null;

	// Handle message
	// messages posted to the handler
	private static final int HANDLER_MESSAGE_BASE = 0;
	private static final int SHOW_BACKUP_BEGIN = HANDLER_MESSAGE_BASE + 3;
	private static final int SHOW_BACKUP_END = HANDLER_MESSAGE_BASE + 4;
	private static final int UNINSTALL_PKG = HANDLER_MESSAGE_BASE + 5;
	private static final int MSG_REFRESH_DATA = HANDLER_MESSAGE_BASE + 6;
	//
	private static final String KEY = "isSystemApp";
	//
	private boolean isSystemApp = false;
	//

	private static final String WAITDLG = "waitingDlg";
	private SharedPreferences prefs = null;
	private final Handler mHandler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case MSG_REFRESH_DATA: {
				new DBTask().execute(MainApp.sMainActivity);
			}
				break;
			case SHOW_BACKUP_BEGIN:
				break;
			case SHOW_BACKUP_END:
				DialogHelper.Toast(R.string.backup_ok, true);
				break;
			case UNINSTALL_PKG:
				UpdataDisplay(getApkinfoList());
				int result = (Integer) msg.obj;
				if (result == 0) {
					DialogFragment waitingDlg = DialogHelper
							.createWaitingDialog(R.string.uninstalling);
					showDialog(getFragmentManager(), waitingDlg, WAITDLG);
				} else if (result == 1) {
					dismissDialog(getFragmentManager(), WAITDLG);
				} else if (result == 2) {
					DialogHelper.Toast(R.string.uninstall_fail, false);
				} else if (result == 3) {
					DialogHelper.Toast(R.string.uninstall_rootfail, false);
				}
				break;
			default:
				break;
			}
		}
	};

	public static UninstallFragment newInstance(boolean isSystemApp) {
		UninstallFragment fragment = new UninstallFragment();
		Bundle args = new Bundle();
		args.putBoolean(KEY, isSystemApp);
		fragment.setArguments(args);
		return fragment;
	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		Bundle args = getArguments();
		isSystemApp = args.getBoolean(KEY);
		prefs = PreferenceManager
				.getDefaultSharedPreferences(MainApp.sInstance);
	}

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		View view = initView(inflater, container, savedInstanceState);
		return view;
	}

	@Override
	public void onResume() {
		super.onResume();
	}

	@Override
	public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
		super.onCreateOptionsMenu(menu, inflater);
		menu.clear();
		MenuItem item;
		item = menu.add(0, MENU_SEARCH, 0, R.string.search);
		item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
		item = menu.add(0, MENU_SORT, 0, R.string.sort);
		item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
		item = menu.add(0, MENU_ABOUT, 0, R.string.about);
		item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case MENU_ABOUT:
			showAlertDialog(DIALOG_ABOUT);
			break;
		case MENU_SORT:
			showAlertDialog(DIALOG_SORT);
			break;
		case MENU_SEARCH:
			showAlertDialog(DIALOG_SEARCH);
			break;
		default:
			break;
		}
		return super.onOptionsItemSelected(item);
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
	}

	class DBTask extends AsyncTask<Context, Integer, ArrayList<ApkInfo>> {

		@Override
		protected ArrayList<ApkInfo> doInBackground(Context... params) {
			return getApkinfoList();
		}

		@Override
		protected void onProgressUpdate(Integer... values) {
			super.onProgressUpdate(values);
		}

		@Override
		protected void onCancelled() {
			SLog.d(TAG, "onCancelled.................");
			super.onCancelled();
		}

		@Override
		protected void onPreExecute() {
			SLog.d(TAG, "onPreExecute..............");
			if (mApkInfoList == null && MainApp.sMainActivity != null) {
				MainApp.sMainActivity
						.setProgressBarIndeterminateVisibility(true);
			}
			super.onPreExecute();
		}

		@Override
		protected void onPostExecute(ArrayList<ApkInfo> result) {
			SLog.d(TAG, "onPostExecute.................");
			if (mApkInfoList == null && MainApp.sMainActivity != null) {
				MainApp.sMainActivity
						.setProgressBarIndeterminateVisibility(false);
			}
			UpdataDisplay(result);

		}
	}

	// init views
	private View initView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		View ly = inflater.inflate(R.layout.uninstall, container, false);
		mListView = (ListView) ly.findViewById(R.id.uninstall_list);

		TextView headerview = (TextView) ly.findViewById(R.id.header);
		if (isSystemApp) {
			headerview.setVisibility(View.VISIBLE);
		} else {
			headerview.setVisibility(View.GONE);
		}
		// set listview click listener
		mListView.setOnItemClickListener(this);
		// init mAdapter
		mAdapter = new AppListAdapter(
				MainApp.sMainActivity.getLayoutInflater(),
				new ArrayList<ApkInfo>());
		// set Adapter of listActivity
		mListView.setAdapter(mAdapter);
		mListView.setOnItemLongClickListener(this);
		return ly;
	}

	// sync data between DB and Android Phone
	private ArrayList<ApkInfo> getApkinfoList() {
		long startTime = SystemClock.currentThreadTimeMillis();
		// 过滤出用户的应用列表
		ArrayList<ApkInfo> userAppList = new ArrayList<ApkInfo>();
		PackageManager pkManager = MainApp.sMainActivity.getPackageManager();
		List<PackageInfo> allAppList = pkManager.getInstalledPackages(0);
		// Get User app list
		for (PackageInfo pkinfo : allAppList) {

			if (isSystemApp) {
				// 获取系统应用
				if ((pkinfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) > 0) {
					userAppList.add(new ApkInfo(pkManager, pkinfo));
				}
			} else {
				// 获取用户应用
				if ((pkinfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) <= 0) {
					userAppList.add(new ApkInfo(pkManager, pkinfo));
				}
			}

		}
		// 排序
		changeSort(userAppList);
		long endTime = SystemClock.currentThreadTimeMillis();
		SLog.d("Time-Consume", "getApkinfoList = " + (endTime - startTime)
				+ " ms");
		return userAppList;
	}

	// processdialog
	private static final int PROGRESS_DIALOG_CREATE_SCAN = 0;
	private static final int PROGRESS_DIALOG_CREATE_BACKUP = 1;
	private static final int PROGRESS_DIALOG_UPDETE = 2;
	private static final int PROGRESS_DIALOG_FINISH = 3;
	private static final int PROGRESS_DIALOG_CANCEL = 4;

	private ProgressDialog mProgressDialog = null;
	private final Handler mHandleProgressDialog = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			int MaxProgress = msg.arg1;
			int CurProgress = msg.arg2;
			switch (msg.what) {
			case PROGRESS_DIALOG_CREATE_SCAN:
				showProgress(R.string.scan, MaxProgress, CurProgress);
				break;
			case PROGRESS_DIALOG_CREATE_BACKUP:
				showProgress(R.string.backup, MaxProgress, CurProgress);
				break;
			case PROGRESS_DIALOG_CANCEL:
			case PROGRESS_DIALOG_FINISH:
				closeProgress();
				break;
			case PROGRESS_DIALOG_UPDETE:
				if (mProgressDialog != null) {
					mProgressDialog.setMax(MaxProgress);
					mProgressDialog.setProgress(CurProgress);
				}
				break;
			default:
				break;
			}
		}
	};

	private void showProgress(int resid, int MaxProgress, int CurProgress) {
		if (mProgressDialog == null) {
			mProgressDialog = new ProgressDialog(MainApp.sMainActivity);
			mProgressDialog.setTitle(getResources().getString(resid));
			mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
			mProgressDialog.setMax(MaxProgress);
			mProgressDialog.setProgress(CurProgress);
			mProgressDialog.setCancelable(false);
			mProgressDialog.show();
		}
	}

	//
	private void closeProgress() {
		if (mProgressDialog != null) {
			mProgressDialog.cancel();
			mProgressDialog = null;
		}
	}

	@Override
	public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
		mAdapter.checkPos(position);
	}

	final BackupListener listener = new BackupListener() {
		@Override
		public void onBackup(final String file, final String name,
				final long size) {
			if (backupDlg != null)
				backupDlg.dismiss();
			new Thread(new Runnable() {
				@Override
				public void run() {
					//
					mHandler.sendEmptyMessage(SHOW_BACKUP_BEGIN);
					Message msg = Message.obtain(mHandleProgressDialog,
							PROGRESS_DIALOG_CREATE_BACKUP, (int) (size >> 10),
							0);
					mHandleProgressDialog.sendMessage(msg);
					String path = SharePreferences.getBackupPath();
					File f = new File(path);
					f.mkdirs();

					FileUtils.CopyFile(file, path + name + ".apk",
							new ProcessCallback() {

								@Override
								public void onProcess(int cursize) {
									Message msg = Message.obtain(
											mHandleProgressDialog,
											PROGRESS_DIALOG_UPDETE,
											(int) (size >> 10), cursize);
									mHandleProgressDialog.sendMessage(msg);
								}
							});
					msg = Message.obtain(mHandleProgressDialog,
							PROGRESS_DIALOG_FINISH, (int) (size >> 10),
							(int) (size >> 10));
					mHandleProgressDialog.sendMessage(msg);
					mHandler.sendEmptyMessage(SHOW_BACKUP_END);
				}
			}).start();
		}
	};

	BackupDlgFragment backupDlg = null;

	// backup apk to sdcard
	private void backup(final String file, final String name, final long size) {
		if (file == null)
			return;
		backupDlg = DialogHelper.createBackupDialog(file, name, size, listener);
		backupDlg.show(getFragmentManager(), "backdlg");
	}

	private void UpdataDisplay(ArrayList<ApkInfo> list) {
		mApkInfoList = PickByString(list, mCurFilter);
		mAdapter.update(mApkInfoList);
	}

	private ArrayList<ApkInfo> PickByString(ArrayList<ApkInfo> ApkInfoList,
			String filter) {
		if (TextUtils.isEmpty(filter))
			return ApkInfoList;
		for (int i = 0; i < ApkInfoList.size(); i++) {
			if (!(ApkInfoList.get(i).appName.toLowerCase().contains(filter
					.toLowerCase()))) {
				ApkInfoList.remove(i);
				i--;
			}
		}
		return ApkInfoList;
	}

	final SortListener sortListener = new SortListener() {
		@Override
		public void onSort(int sortType) {
			SharePreferences.setSortType(sortType);
			UpdataDisplay(getApkinfoList());
		}
	};

	private void showAlertDialog(int dialogID) {
		switch (dialogID) {
		case DIALOG_ABOUT:
			DialogHelper.showAboutDialog(getFragmentManager());
			break;
		case DIALOG_SORT:
			DialogHelper.showSortDialog(getFragmentManager(), sortListener);
			break;
		case DIALOG_SEARCH:
			DialogHelper.showSearchDialog(getFragmentManager());
			break;
		default:
			break;
		}
	}

	public static final int SORT_BY_TIME_DESC = 1;
	public static final int SORT_BY_TIME_ASC = 2;
	public static final int SORT_BY_NAME_DESC = 3;
	public static final int SORT_BY_NAME_ASC = 4;

	private void changeSort(ArrayList<ApkInfo> list) {
		int type = SharePreferences.getSortType();
		switch (type) {
		case Define.SORT_BY_TIME_DESC:
			Collections.sort(list, new Comparator<ApkInfo>() {

				@Override
				public int compare(ApkInfo lhs, ApkInfo rhs) {
					if (lhs.modifiedTime > rhs.modifiedTime) {
						return -1;
					} else if (lhs.modifiedTime < rhs.modifiedTime) {
						return 1;
					} else {
						return 0;
					}
				}
			});
			break;
		case Define.SORT_BY_TIME_ASC:
			Collections.sort(list, new Comparator<ApkInfo>() {

				@Override
				public int compare(ApkInfo lhs, ApkInfo rhs) {
					if (lhs.modifiedTime > rhs.modifiedTime) {
						return 1;
					} else if (lhs.modifiedTime < rhs.modifiedTime) {
						return -1;
					} else {
						return 0;
					}
				}
			});
			break;
		case Define.SORT_BY_NAME_DESC:
			Collections.sort(list, new Comparator<ApkInfo>() {

				@Override
				public int compare(ApkInfo lhs, ApkInfo rhs) {
					return rhs.appName.compareTo(lhs.appName);
				}
			});
			break;
		case Define.SORT_BY_NAME_ASC:
			Collections.sort(list, new Comparator<ApkInfo>() {

				@Override
				public int compare(ApkInfo lhs, ApkInfo rhs) {
					return lhs.appName.compareTo(rhs.appName);
				}
			});
			break;
		default:
			break;
		}
	}

	@Override
	public void onUninstallClick() {
		final boolean isBackup = (prefs != null) ? prefs.getBoolean("backup",
				true) : true;
		new Thread(new Runnable() {
			@Override
			public void run() {
				if (mAdapter != null) {
					ArrayList<ApkInfo> list = mAdapter.getCheckedList();
					if (list.size() == 0)
						return;
					Message msgstart = new Message();
					msgstart.what = UNINSTALL_PKG;
					msgstart.obj = 0; // 开始
					mHandler.sendMessage(msgstart);
					for (ApkInfo info : list) {
						if (isBackup)
							PackageUtils.backupApp(info.dataDir, info.appName);
						if (isSystemApp) {
							PackageUtils.uninstall_root_sys(
									MainApp.sMainActivity, info, UNINSTALL_PKG,
									mHandler);
						} else {
							PackageUtils.uninstall_root_app(
									MainApp.sMainActivity, info, UNINSTALL_PKG,
									mHandler);
						}
					}
					Message msgend = new Message();
					msgend.what = UNINSTALL_PKG;
					msgend.obj = 1; // 结束
					mHandler.sendMessageDelayed(msgend, 1000);
				}
			}
		}).start();

	}

	@Override
	public void onSelAllClick() {
		if (mAdapter != null)
			mAdapter.checkAll();
	}

	@Override
	public void onUnSelAllClick() {
		if (mAdapter != null)
			mAdapter.uncheckAll();
	}

	@Override
	public void onDeleteClick() {
		Intent intent = new Intent(MainApp.sMainActivity, Preference.class);
		startActivity(intent);
	}

	@Override
	public void onLoadData(boolean bforceUpdate) {
		// 当数据没有的时候 再获取数据
		if (mApkInfoList == null || bforceUpdate)
			new DBTask().execute(MainApp.sMainActivity);
	}

	OptionListener optionListener = new OptionListener() {

		@Override
		public void Option(int id, int pos) {
			ApkInfo info = (ApkInfo) mAdapter.getItem(pos);
			switch (id) {
			case 0: // 运行
				PackageUtils.startAPP(MainApp.sMainActivity, info.packageName);
				break;
			case 1: // 查看详情
				PackageUtils.showInstalledAppDetails(MainApp.sMainActivity,
						info.packageName);
				break;
			case 2: // 备份
				backup(info.dataDir, info.appName + info.version, info.apkSize);
				break;
			default:
				break;
			}
		}
	};

	@Override
	public boolean onItemLongClick(AdapterView<?> parent, View view,
			int position, long id) {
		OptionDlgFragment dlg = DialogHelper.createOptionDialog(position,
				optionListener);
		dlg.show(getFragmentManager(), "optionDlg");
		return true;
	}

}
